package com.njmaomao.gj.pyot.domain.yto;

import com.njmaomao.gj.pyot.common.Utils;
import com.njmaomao.gj.pyot.common.XmlUtil;
import com.njmaomao.gj.pyot.config.Bizs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.TreeMap;
import java.util.stream.Collectors;

import static com.njmaomao.gj.pyot.config.Bizs.SIGN_TYPE;

@Component
@Slf4j
public class YtoApiService extends YtApiService {

    /**
     * 订单服务类
     */
    //TODO 校验码
    protected String partnerId = "123456";
    //TODO 客户编码
    protected String clientId = "TEST";

    @Value("${yto.url.orderCreate}")
    private String orderCreateUrl;

    @Value("${yto.url.orderCancel}")
    private String orderCancelUrl;

    /**
     * 电子面单类
     */
    //TODO 校验码
    protected String epartnerId = "u2Z1F7Fh";
    //TODO 客户编码
    protected String eclientId = "K21000119";

    @Value("${yto.url.eordercreate}")
    private String eordercreateUrl;

    @Value("${yto.url.eOrdApply}")
    private String eOrdApplyUrl;

    /**
     * 查询服务类
     */
    //TODO 校验码
    protected String qpartnerId = "1QLlIZ";
//    protected String qpartnerId = "123456";
    //TODO 客户编码
    protected String qclientId = "YTOTEST";

    protected String appKey = "sF1Jzn";

    @Value("${yto.url.waybillQuery}")
    private String waybillQueryUrl;

    @Value("${yto.url.chargeQuery}")
    private String chargeQueryUrl;

    @Autowired
    private RestTemplate restTemplate;

    public Response orderCreate(RequestOrder requestOrder) {
        return ytpost(orderCreateUrl, requestOrder, Response.class, partnerId, clientId, "online");
    }

    public Response orderCancel(UpdateInfo updateInfo) {
        return ytpost(orderCancelUrl, updateInfo, Response.class, partnerId, clientId, "online");
    }

    public MianResponse eorderCreate(MianRequestOrder requestOrder) {
        return ytpost(eordercreateUrl, requestOrder, MianResponse.class, epartnerId, eclientId, "offline");
    }

    public MianResponse eOrdApply(MianRequestOrder requestOrder) {
        return ytpost(eOrdApplyUrl, requestOrder, MianResponse.class, epartnerId, eclientId, "offline");
    }

    public WaybillQueryResponse waybillQuery(String billNo) {
        TreeMap<String, String> paramMap = new TreeMap<>();

        paramMap.put("app_key", appKey);
        paramMap.put("method", "yto.Marketing.WaybillTrace");
        paramMap.put("timestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        paramMap.put("user_id", qclientId);
        paramMap.put("v", "1.01");
        paramMap.put("format", "XML");

        String collectStr = paramMap.entrySet().stream().map(e -> String.join("", e.getKey(), e.getValue())).collect(Collectors.joining(""));
        String preSignStr = qpartnerId + collectStr;
        log.info("preSignStr: {}", preSignStr);

        String sign = Bizs.md5(preSignStr, SIGN_TYPE).toUpperCase();
        log.info("sign: {}", sign);
        paramMap.put("sign", sign);

        String param = "<?xml  version=\"1.0\"?>\n" +
                "<ufinterface>\n" +
                "<Result>\n" +
                "<WaybillCode>\n" +
                "<Number>" + billNo + "</Number>\n" +
                "</WaybillCode>\n" +
                "</Result>\n" +
                "</ufinterface>";

        paramMap.put("param", param);



        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        paramMap.entrySet().stream().forEach(e -> params.add(e.getKey(), e.getValue()));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("accept", "*/*");
        headers.add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

        String url = waybillQueryUrl;
        String paramStr = params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue().get(0)).collect(Collectors.joining("&"));
        log.info("YtApiService.ytpost url:{}, paramStr:{}", url, paramStr);
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);

        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);

        String body = responseEntity.getBody();
        log.info("YtApiService.ytpost url:{}, resp: {}", url, body);

        if(body.startsWith("<ufinterface>")) {
            return XmlUtil.xml2Bean(body, WaybillQueryResponse.class);
        }

        WbqResponse response = XmlUtil.xml2Bean(body, WbqResponse.class);
        WaybillQueryResponse waybillQueryResponse = new WaybillQueryResponse();
        waybillQueryResponse.setResponse(response);

        return waybillQueryResponse;

    }

    public ChargeQueryResponse chargeQueryUrl(TransportInfo transportInfo) {
        TreeMap<String, String> paramMap = new TreeMap<>();

        paramMap.put("app_key", appKey);
        paramMap.put("method", "yto.Marketing.TransportPrice");
        paramMap.put("timestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        paramMap.put("user_id", qclientId);
        paramMap.put("v", "1.01");
        paramMap.put("format", "XML");

        String collectStr = paramMap.entrySet().stream().map(e -> String.join("", e.getKey(), e.getValue())).collect(Collectors.joining(""));
        String preSignStr = qpartnerId + collectStr;
        log.info("preSignStr: {}", preSignStr);

        String sign = Bizs.md5(preSignStr, SIGN_TYPE).toUpperCase();
        log.info("sign: {}", sign);
        paramMap.put("sign", sign);

        String param = "<?xml  version=\"1.0\"?>\n" +
                "<ufinterface>\n" +
                "<Result>\n" +
                XmlUtil.objectToXml(transportInfo) + "\n" +
                "</Result>\n" +
                "</ufinterface>";

        paramMap.put("param", param);



        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        paramMap.entrySet().stream().forEach(e -> params.add(e.getKey(), e.getValue()));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("accept", "*/*");
        headers.add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

        String url = chargeQueryUrl;
        String paramStr = params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue().get(0)).collect(Collectors.joining("&"));
        log.info("YtApiService.ytpost url:{}, paramStr:{}", url, paramStr);
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);

        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);

        String body = responseEntity.getBody();
        log.info("YtApiService.ytpost url:{}, resp: {}", url, body);

        if(body.startsWith("<")) {
            return XmlUtil.xml2Bean(body, ChargeQueryResponse.class);
        }

        ChargeQueryResponse chargeQueryResponse = new ChargeQueryResponse();
        chargeQueryResponse.setSuccess("true");
        chargeQueryResponse.setPrice(body);
        return chargeQueryResponse;
    }

    public static void main(String[] args) {
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Response><code>400</code><reason>HTTP请求出错</reason><success>false</success></Response>";

        WbqResponse response = XmlUtil.xml2Bean(xml, WbqResponse.class);

        log.info(Utils.toJson(response));
    }



}
